<template>
	<li :class="classes" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave">
		<div class="ivu-menu-submenu-title" ref="reference" @click.stop="handleClick" :style="titleStyle">
			<slot name="title"></slot>
			<icon
				:type="arrowType"
				:custom="customArrowType"
				:size="arrowSize"
				class="ivu-menu-submenu-title-icon"
			/>
		</div>
		<collapse-transition v-if="menuMode === 'vertical'">
			<ul class="ivu-menu" v-show="opened">
				<slot></slot>
			</ul>
		</collapse-transition>
		<transition name="slide-up" v-else>
			<drop-item v-show="opened" placement="bottom" ref="drop" :style="dropStyle">
				<ul class="ivu-menu-drop-list">
					<slot></slot>
				</ul>
			</drop-item>
		</transition>
	</li>
</template>
<script lang="ts">
	import Anes from "../base";
	import { Prop, Component, Watch } from "vue-property-decorator";
	import DropItem from "../select/drop.vue";
	import Icon from "../icon/icon.vue";
	import CollapseTransition from "../collapseTransition";
	import {
		getStyle,
		findComponentsDownward,
		findComponentsUpward,
		findComponentUpward
	} from "../../utils/assist";
	import Menu from "./menu.vue";

	@Component({
		name: "Submenu",
		components: { Icon, DropItem, CollapseTransition }
	})
	export default class Submenu extends Anes {
		@Prop({ type: [String, Number], required: true }) name!: string | number;
		@Prop({ type: Boolean, default: false }) disabled!: boolean;

		active = false;
		opened = false;
		timeout = 0;
		dropWidth = 0;

		get classes() {
			return [
				`ivu-menu-submenu`,
				{
					[`ivu-menu-item-active`]: this.active && !this.hasParentSubmenu,
					[`ivu-menu-opened`]: this.opened,
					[`ivu-menu-submenu-disabled`]: this.disabled,
					[`ivu-menu-submenu-has-parent-submenu`]: this.hasParentSubmenu,
					[`ivu-menu-child-item-active`]: this.active
				}
			];
		}
		get parentSubmenuNum() {
			return findComponentsUpward<Submenu>(this, "Submenu").length;
		}
		get hasParentSubmenu() {
			return this.parentSubmenuNum > 0;
		}

		get menuMode() {
			return this.menu?.mode;
		}
		get menu() {
			return findComponentUpward<Menu>(this, "Menu");
		}
		get menuAccordion() {
			return this.menu?.accordion;
		}
		get dropStyle() {
			if (this.dropWidth) {
				return { minWidth: `${this.dropWidth}px` };
			} else {
				return {};
			}
		}

		get titleStyle() {
			if (this.hasParentSubmenu && this.menuMode !== "horizontal") {
				return {
					paddingLeft: 43 + (this.parentSubmenuNum - 1) * 24 + "px"
				};
			} else {
				return {};
			}
		}
		// 3.4.0, global setting customArrow 有值时，arrow 赋值空
		get arrowType() {
			let type = "ios-arrow-down";
			if (this.$IVIEW) {
				if (this.$IVIEW.menu.customArrow) {
					type = "";
				} else if (this.$IVIEW.menu.arrow) {
					type = this.$IVIEW.menu.arrow;
				}
			}
			return type;
		}
		// 3.4.0, global setting
		get customArrowType() {
			let type = "";

			if (this.$IVIEW) {
				if (this.$IVIEW.menu.customArrow) {
					type = this.$IVIEW.menu.customArrow;
				}
			}
			return type;
		}
		// 3.4.0, global setting
		get arrowSize() {
			let size: string | number = "";
			if (this.$IVIEW) {
				if (this.$IVIEW.menu.arrowSize) {
					size = this.$IVIEW.menu.arrowSize;
				}
			}
			return size;
		}

		get drop() {
			return this.$refs.drop as DropItem;
		}

		mounted() {
			const width = getStyle(this.$el as HTMLElement, "width");
			if (width) {
				this.dropWidth = parseFloat(width.replace("px", ""));
			}

			//	this.$options.name = "Submenu";
			this.$on("on-menu-item-select", (name: string) => {
				if (this.menuMode === "horizontal") this.opened = false;
				this.menu?.$emit("on-menu-item-select", name);
				//	this.dispatch<Menu>("on-menu-item-select", name);
				return true;
			});
			this.$on("on-update-active-name", (status: boolean) => {
				findComponentUpward<Submenu>(this, "Submenu")?.$emit(
					"on-update-active-name",
					status
				);

				if (findComponentsDownward(this, "Submenu"))
					findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
						item.active = false;
					});
				this.active = status;
			});
		}

		handleMouseenter() {
			if (this.disabled) return;
			if (this.menuMode === "vertical") return;

			clearTimeout(this.timeout);
			this.timeout = setTimeout(() => {
				this.menu?.updateOpenKeys(this.name);
				this.opened = true;
			}, 250);
		}
		handleMouseleave() {
			if (this.disabled) return;
			if (this.menuMode === "vertical") return;

			clearTimeout(this.timeout);
			this.timeout = setTimeout(() => {
				this.menu?.updateOpenKeys(this.name);
				this.opened = false;
			}, 150);
		}
		handleClick() {
			if (this.disabled) return;
			if (this.menuMode === "horizontal") return;
			const opened = this.opened;
			if (this.menuAccordion) {
				this.$parent.$children.forEach(item => {
					if (item.$options.name === "Submenu") (item as Submenu).opened = false;
				});
			}
			this.opened = !opened;
			this.menu?.updateOpenKeys(this.name);
		}
		@Watch("mode")
		onmodechange(val: string) {
			if (val === "horizontal") {
				this.drop?.update();
			}
		}

		@Watch("opened")
		onOpenedChange(val: boolean) {
			if (this.menuMode === "vertical") return;
			if (val) {
				// set drop a width to fixed when menu has fixed position
				//	this.dropWidth = parseFloat(getStyle(this.$el, "width"));
				this.drop?.update();
			} else {
				this.drop?.destroy();
			}
		}
	}
</script>
